﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using AlgoritimoGenetico.utils;

namespace AlgoritimoGenetico.dados
{
    public static class RepositorioCidades
    {
        #region Atributos
        public static bool flag = false;
        public static List<Cidade> Cidades = null;
        private static List<GenericPair<string, int>> _IndiceCidades = null;
        private static float[,] _DistanciasCidades = null;
        #endregion

        #region Métodos
        public static void GerarCidades(DateTime mesReferencia)
        {
            if (!flag)
            {
                Cidades = Utils.LerCidades(mesReferencia);
                _IndiceCidades = Utils.GetIndicesCidades();
                _CarregarDistanciaCidades();
                flag = true;
            }
        }

        private static void _CarregarDistanciaCidades()
        {
            _DistanciasCidades = Utils.LerDistanciaCidades();
            _NormalizarDistancias();
        }

        private static int _GetIdxCidade(string nomeCidade)
        {
            int idx = -1;
            idx = _IndiceCidades.Find( p => string.Equals(p.First, nomeCidade)).Second;
            if (idx == -1)
                throw new Exception("Indice da Cidade não existe!!!");
            return idx;
        }
        /// <summary>
        /// Retorna a distância entre duas cidades
        /// </summary>
        /// <param name="nomeCidade1"></param>
        /// <param name="nomeCidade2"></param>
        /// <returns></returns>
        public static float GetDistanciaCidades(string nomeCidade1, string nomeCidade2)
        {
            float distancia = -1;
            int idx1 = _GetIdxCidade(nomeCidade1);
            int idx2 = _GetIdxCidade(nomeCidade2);

            distancia = _DistanciasCidades[idx1, idx2];

            if(distancia == -1)
                 throw new Exception("Distância entre as cidades não existe!!!");
            return distancia;
        }

        /// <summary>
        /// Normaliza as distâncias entre as cidades entre 0 e 125
        /// </summary>
        private static void _NormalizarDistancias()
        {
            int i,j = 0;
            float maior = 0;
            float menor = float.MaxValue;

            for (i = 0; i < Utils.NumeroCidades; i++)
                for (j = 0; j < Utils.NumeroCidades; j++)
                {
                    if (_DistanciasCidades[i, j] < menor)
                        menor = _DistanciasCidades[i, j];

                    if (_DistanciasCidades[i, j] > maior)
                        maior = _DistanciasCidades[i, j];
                }

            for (i = 0; i < Utils.NumeroCidades; i++)
            {
                for (j = 0; j < Utils.NumeroCidades; j++)
                {
                    _DistanciasCidades[i, j] = (125 * (_DistanciasCidades[i, j] - menor) / (maior - menor));
                }
               
            }
        }

        public static Cidade GetCidadeByNome(string nome)
        {
            return Cidades.Find(c => c.Nome.Equals(nome));
        }
        #endregion
    }
}